#include"preCmpH.h"
#include"UIFontManager.h"

BEGIN_NAMESPACE(ui_manager)
BEGIN_NAMESPACE(ui_fonts)

UIFontManager::UIFontManager()
{
	
}
UIFontManager::~UIFontManager()
{

}
UIFontManager& UIFontManager::getInstance()
{
	static UIFontManager* instance = null;
	if(instance == null)
	{
		instance = new UIFontManager();
	}
	return *instance;
}
UIFont UIFontManager::LoadFont(std::string path)
{
	FT_Face temp;
	FT_New_Face( ft_lib_, path.c_str(), 0, &temp);
	loaded_faces_.push_back(temp);
	std::string name(temp->family_name);
	UIFont f;
	f.SetId(temp->face_index);
	f.SetSize(12);
	f.SetName(name);
	return f;
}
UIFont UIFontManager::GetDefault()
{
	std::string name(default_->family_name);
	UIFont f;
	f.SetId(default_->face_index);
	f.SetSize(12);
	f.SetName(name);
	return f;
}
FT_BBox GetStringBox(std::vector<FT_Glyph>& glyphs, std::vector<FT_Vector>& pos,int num_glyphs)
{
	FT_BBox bbox;
	/* initialize string bbox to "empty" values */ 
	bbox.xMin = bbox.yMin = 32000;
	bbox.xMax = bbox.yMax = -32000;
	/* for each glyph image, compute its bounding box, */
	/* translate it, and grow the string bbox */
	for (int n = 0; n < num_glyphs; n++ ) {
		FT_BBox glyph_bbox;
		FT_Glyph_Get_CBox( glyphs[n], ft_glyph_bbox_pixels, &glyph_bbox );
		glyph_bbox.xMin += pos[n].x;
		glyph_bbox.xMax += pos[n].x;
		glyph_bbox.yMin += pos[n].y;
		glyph_bbox.yMax += pos[n].y;
		if ( glyph_bbox.xMin < bbox.xMin ) 
			bbox.xMin = glyph_bbox.xMin;
		if ( glyph_bbox.yMin < bbox.yMin )
			bbox.yMin = glyph_bbox.yMin; 
		if ( glyph_bbox.xMax > bbox.xMax )
			bbox.xMax = glyph_bbox.xMax;
		if ( glyph_bbox.yMax > bbox.yMax )
			bbox.yMax = glyph_bbox.yMax;
	} /* check that we really grew the string bbox */ 
	if ( bbox.xMin > bbox.xMax ) { 
		bbox.xMin = 0; bbox.yMin = 0;
		bbox.xMax = 0; bbox.yMax = 0;
	} /* return string bbox */
	return bbox;
}
int ExtractGlyphImages(FT_Face& face, std::vector<FT_Glyph>& glyphs, std::vector<FT_Vector>& pos,const char* text)
{
	int error;
	FT_GlyphSlot slot = face->glyph;
	FT_UInt glyph_index;
	FT_Bool use_kerning = FT_HAS_KERNING( face );
	FT_UInt previous = 0;
	int pen_x = 0;
	int pen_y = 0;
	FT_UInt num_glyphs = 0;
	int lenght = strlen(text);

	for (int n = 0; n < lenght; n++ ) {
		glyph_index = FT_Get_Char_Index( face, text[n] );
		if ( use_kerning && previous && glyph_index ) { 
			FT_Vector delta;
			FT_Get_Kerning( face, previous, glyph_index, FT_KERNING_DEFAULT, &delta );
			pen_x += delta.x / 64;
		}
		pos[num_glyphs].x = pen_x;
		pos[num_glyphs].y = pen_y;
		error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
		if ( error ) continue;
		error = FT_Get_Glyph( face->glyph, &glyphs[num_glyphs] );
		if ( error ) continue;
		pen_x += slot->advance.x / 64;
		previous = glyph_index;
		num_glyphs++;
	}
	return num_glyphs;
}
void UIFontManager::LoadText(UIFont font, std::string text)
{
	if(text.empty()){
		throw std::exception("No Text");
	}
	std::list<FT_Face>::iterator it;
	FT_Face* face;
	for(it = loaded_faces_.begin(); it != loaded_faces_.end(); it++)
	{
		if( (*it)->face_index == font.GetId()){
			face = &(*it);
			break;
		}
	}
	if(it == loaded_faces_.end()){
		face = &default_;
	}

	int size = text.length();
	if(nr_glyphs_ < size ){
		FT_Glyph temp;
		FT_Vector temp2;
		int count = size - nr_glyphs_;
		glyphs_.insert(glyphs_.begin(), count, temp);
		pos_.insert(pos_.begin(), count, temp2);
	}
	FT_Set_Char_Size( *face,0, font.GetSize()*64,0,96);
	//FT_Set_Pixel_Sizes(*face, 0, font.GetSize() * ( 96.0f/ 72.0f));
	nr_glyphs_ = ExtractGlyphImages(*face, glyphs_, pos_,text.c_str());
	FT_BBox string_box = GetStringBox(glyphs_, pos_, nr_glyphs_);
	
	font_h_ = font.GetSize() * (int)(96.0f / 64.0f);
	
	int w = string_box.xMax;
	int h = (string_box.yMax - string_box.yMin) * (int)(96.0f / 64.0f);
	text_size_.setWidth(w);
	text_size_.setHeight(h);
}
UIFontChar UIFontManager::GetChar(int index) const
{
	FT_Vector pen;
	pen.x = pos_[index].x * 64;
	pen.y = pos_[index].y * 64;
	FT_Glyph_To_Bitmap( (FT_Glyph*)&glyphs_[index], FT_RENDER_MODE_NORMAL, &pen, 1 );
	FT_BitmapGlyph bit = (FT_BitmapGlyph)glyphs_[index];
	
	UIFontChar temp;
	temp.SetPosX(bit->left);
	temp.SetPosY(font_h_ - bit->top);
	temp.SetWidth(bit->bitmap.width);
	temp.SetHeight(bit->bitmap.rows);
	temp.SetBuffer(bit->bitmap.buffer);

	return temp;
}
void UIFontManager::Clear()
{
	for(uint i = 0; i < glyphs_.size(); i++)
	{
		//FT_Done_Glyph(glyphs_[i]);
		
	}
}

void UIFontManager::StartUp( UIManager& manager )
{
	ft_lib_ = null;
	default_ = null;
	nr_glyphs_ = 0;
	loaded_ = false;

	FT_Init_FreeType( &ft_lib_ );
	int error = FT_New_Face( ft_lib_, "res/arial.ttf", 0, &default_);
	if(error){
		throw std::exception("Failed to Load Default Font");
	}
}

void UIFontManager::ShutDown()
{

}




END_NAMESPACE // ui fonts
END_NAMESPACE // ui manager